<?php
/**
 * @file			admin.base.php
 * @CopyRight		(C)1996-2099 SINA Inc.
 * @Project			Waitan
 * @Author			guanghui <guanghui1@staff.sina.com.cn>
 * @Create Date:	2011-08-12
 * @Modified By:	guanghui/2011-08-12
 * @Brief			管理后台控制器基类
 */
 
class admin_base
{
	const ADMIN_COUNT_PAGE = 20;  //每页显示记录数
	const ADMIN_LINK_NUM_PAGE = 10;  //分页链接数
	const ADMIN_SESSION_CURRENT_URL = '__ADMIN_CURRENT_URL';  //当前的URL SESSION索引，用于操作后返回当前页面
	
	private $_router_info;
	
	/**
	* 权限划分
	* 
	* @var array
	*/
	protected $_permissions = array(
									1 => array('name' => '周边景点', 'module' => array('focus_map.*', 'hot_spots.*', 'recom_tag.*')),
									2 => array('name' => '周边行程', 'module' => array('recom_stroke.*', 'focus_map.*', 'recom_tag.*', 'hot_stroke.*')),
									3 => array('name' => '达人管理', 'module' => array('focus_map.*', 'user_show.*')),
									4 => array('name' => '专题管理（新）', 'module' => array('specialv2.*', 'focus_map.*')),
									5 => array('name' => '游记管理', 'module' => array('youji.*')),
									6 => array('name' => '后台账号管理', 'module' => array('admin.userList', 'admin.addAdmin', 'admin.delAdmin', 'admin.default_action', 'admin.setPermissions')),
									7 => array('name' => '运营位设置', 'module' => array('admgr.setting')),
									8 => array('name' => '酒店管理', 'module' => array('hotel_weibo.*', 'focus_map.*', 'hotel_wuser.*', 'hotel_wtopic.*', 'hotel_ofcuser.*', 'recom_tag.*', 'hotel_homerecomarticle.*')),
									9 => array('name' => '文章管理', 'module' => array('article.*')),
									10 => array('name' => '旅游情报', 'module' => array('focus_map.*')),
									11 => array('name' => '用户推荐', 'module' => array('auto_fuser.*')),
									12 => array('name' => '首页管理', 'module' => array('headline.*', 'focus_map.*', 'user_show.*', 'home.*', 'admgr.*')),
								);
	
	/**
	* 不作权限控制的模块
	* 
	* @var array
	*/
	private $_noLimitModule = array('jsApi.*', 'upload.*', 'authImage.*', 'admin.index', 'admin.login', 'admin.logout', 'admin.rePwd');
	
	/**
	* 超级管理员列表
	* 
	* @var array
	*/
	protected $_superAdmin = array(1);
	
	public function __construct()
	{
		$this->_router_info = APP::getRuningRoute(true);
		
		//判断管理员是否登录
		if (!USER::isAdminLogin() && !in_array($this->_getRouter('action') , array('login', 'authcode'))) {
			exit('<script>window.top.location.href = "' . URL('admin/admin.login', '', 'admin.php'). '"</script>');
		}
		
		//判断当前登录用户是否有访问当前模块的权限
		if (USER::isAdminLogin()) {
			if (!$this->_chkPermissions($this->_getRouter('module') . '.' . $this->_getRouter('action'))) {
				exit('无权访问');
			}
		}
	}
	
	/**
	* 判断当前登录用户是否有访问当前模块的权限
	* 
	* @param mixed $permission
	*/
	final protected function _chkPermissions($permission)
	{
		if (in_array(USER::aid(), $this->_superAdmin))	return TRUE;
		
		$userPermissions = USER::getAdmin(ADMIN_SESSION_PERMISSIONS);
		static $allows = false;
		if ($allows === false) {
			$allows = $this->_noLimitModule;
			foreach ($userPermissions as $pid) {
				if (empty($pid))	continue;
				$allows = array_merge($allows, $this->_permissions[$pid]['module']);
			}
			$allows = array_unique($allows);
		}
		
		list($module, $action) = explode('.', $permission);
		foreach ($allows  as $item) {
			list($chkModule, $chkAction) = explode('.', $item);
			if (strcasecmp($chkModule, $module) === 0 && ($chkAction === '*' || strcasecmp($chkAction, $action) === 0)) {
				return TRUE;
			}
		}
		
		return FALSE;
	}
	
	/**
	* 初始化管理员SESSION
	* 
	* @param int $admin_id
	* @param string $admin_name
	*/
	final protected function _initAdminSess($admin_id, $admin_name, $permissions, $group_id='')
	{
		USER::setAdmin(ADMIN_SESSION_UID, $admin_id);
		USER::setAdmin(ADMIN_SESSION_UNAME, $admin_name);
		USER::setAdmin(ADMIN_SESSION_PERMISSIONS, explode('|', $permissions));
		USER::setAdmin('group_id', $group_id);
	}
	
	/**
	* 重置管理员SESSION
	* 
	*/
	final protected function _resetAdminSess()
	{
		USER::resetAdmin();
	}
	
	/**
	 * 当前请求的路由信息
	 * @param string $ext 所要返回的数据，为空则返回路由数组
	 * @return mixed
	 */
	final protected function _getRouter($ext = '') {
		switch ($ext) {
			case 'ctrl':
				return trim($this->_router_info['path'], '/\\');
				break;
				
			case 'module':
				return $this->_router_info['class'];
				break;
				
			case 'action':
				return $this->_router_info['function'];
				break;
				
			default:
				return $this->_router_info;
		}
	}
	
	/**
	 * 当前请求方法
	 */
	final protected function _requestMethod()
	{
		return V('s:REQUEST_METHOD');
	}
	
	/**
	 * 当前请求是否为POST方法
	 */
	final protected function _isPost()
	{
		return strtolower($this->_requestMethod()) === 'post';
	}

	/**
	 * 当前请求是否为GET方法
	 *
	 */
	final protected function _isGet()
	{
		return strtolower($this->_requestMethod()) === 'get';
	}

	/**
	* 显示模板
	* 
	* @param string $tpl
	*/
	final protected function _display($tpl = '')
	{
		$tpl = $tpl ? $tpl : $this->_getRouter('module') . '/' . $this->_getRouter('action');
		TPL::display('admin/' . $tpl, '', 0, false);
	}

	/**
	 * 操作失败后提示跳转
	 * @param $msg String 要显示的消息
	 * @param $url String|Array 显示消息3秒后跳转的地址,如果该参数为数据则为路由方式,其中下标为0表示action,1表示module,2表示controller,
	 * @param $errno int 如果设置该参数，则返回json结果
	 */
	final protected function _error($msg, $url = null, $errno=null) {
		if ($errno !== null) {
			APP::ajaxRst(false, $errno, $msg);
		}
		if (is_array($url)) {
			if (empty($url[0])) {
				APP :: tips(array('msg'=> $msg, 'tpl' => 'error', 'baseskin'=>false));
			}
			$module = isset($url[1]) ? $url[1]: $this->_getRouter('module');
			$controller = isset($url[2]) ? $url[2] : $this->_getRouter('ctrl');
			$url = URL( $controller . '/' . $module . '.' . $url[0]);
		}

		$param = array(
					'msg'=> $msg,
					'tpl' => 'admin/error',
					'baseskin'=>false
				);

		if ($url) {
			$param += array(
				'timeout'=>3,
				'location' => $url
			);
		}
		APP :: tips($param);
	}
	
	/**
	 * 操作成功后提示跳转
	 * @param $msg String 要显示的消息
	 * @param $url String|Array 显示消息3秒后跳转的地址,如果该参数为数据则为路由方式,其中下标为0表示action,1表示module,2表示controller,
	 * @param $errno int 如果设置该参数，则返回json结果
	 */
	final protected function _succ($msg, $url = null, $errno=null) {
		if ($errno !== null) {
			APP::ajaxRst(false, $errno, $msg);
		}
		if (is_array($url)) {
			if (empty($url[0])) {
				APP :: tips(array('msg'=> $msg, 'tpl' => 'error', 'baseskin'=>false));
			}
			$module = isset($url[1]) ? $url[1]: $this->_getRouter('module');
			$controller = isset($url[2]) ? $url[2] : $this->_getRouter('ctrl');
			$url = URL( $controller . '/' . $module . '.' . $url[0]);
		}

		$param = array(
					'msg'=> $msg,
					'tpl' => 'admin/success',
					'baseskin'=>false
				);

		if ($url) {
			$param += array(
				'timeout'=>3,
				'location' => $url
			);
		}
		APP :: tips($param);
	}
	
	/**
	* 将当前URL路由写入SESSION,用于自动返回
	* 
	*/
	final protected function _setCurrentUrl($url = '')
	{
		$url = $url ? $url : URL('admin/' . $this->_getRouter('module') . '/' . $this->_getRouter('action'));
		USER::setAdmin(self::ADMIN_SESSION_CURRENT_URL, $url);
	}
	
	/**
	* 设置某个前台用户身份SESSION
	* 用于模拟一个用户身份切换到前台操作
	* 
	* @param mixed $uInfo
	*/
	final protected function _disguiseClient($uInfo)
	{
		USER::uid($uInfo['id']);
		USER::set('uid',$uInfo['id']);
		USER::set('nickname',$uInfo['nickname']);
		USER::set('face_xs',$uInfo['face_xs']);
		USER::set('from_service_id',$uInfo['from_service_id']);
		USER::set('u_firstlogin',FALSE);
		USER::set('u_guidefooter',FALSE);
	}
	
	/**
	* 上传文件基本方法，API分离时需要改造
	* 
	* @param string $field
	* @param bool $is_img 是否图片
	*/
	final protected function _uploadBase($field, $is_img = true, $type = 'original')
	{
		if ($is_img)
			return F::mgrApi('mgr/upload/post', array('img' => 'pic', 'type' => $type, 'data_type' => 3, 'referer' => -1), 'POST');
		else
			return F::mgrApi('mgr/upload/file', array('file' => 'file', 'data_type' => 3, 'referer' => -1), 'POST');
	}
	
	//图片地址上传图片
	final protected function _urlUploadBase($url, $is_img = true, $type = 'original', $referer=-1)
	{
		if (empty($url)) return FALSE;
		if ($url) {
			if ($is_img)
				return F::mgrApi('mgr/upload/post', array('img' => $url, 'type' => $type, 'data_type' => 1, 'referer'=>$referer), 'POST');
			else
				return F::mgrApi('mgr/upload/file', array('file' => $url, 'data_type' => 1), 'POST');
		}
		return FALSE;
	}

	/// 是否忽略指定的控制器
	function _isIgnoreCheckReferer(){
		if(defined('CHECK_REFERER')&&!CHECK_REFERER) return TRUE; //判断是否要检查referrer
		$nowRoute = APP::getRequestRoute(); 
        $ignoreArr = V('-:ignoreReferer');	
		if (in_array($nowRoute,$ignoreArr)) {return true;}
		foreach($ignoreArr as $ig){
			$tig = str_replace('*', '', $ig);
			if (($nowRoute.'.'==$tig) || $tig!=$ig && strpos($nowRoute, $tig)===0 ){
				return true;
			}
		}
		return false;
	}

	//检查来源
	function _checkReferer($isJs = true){
		if($this->_isIgnoreCheckReferer()){
			return true;
		}
		$refre = strtolower(V('s:HTTP_REFERER'));
		$allow_refre = V('-:allow_referer'); //允许访问的来源
		// $refre = "https://asdf.dev.ziyou.com";
		$interrupt = true; //是否中断
		if($refre && $allow_refre){
			$host = false;
			//从URL中获取主机名称
			if( preg_match('@^(?:https?://)([^/]+)@i',$refre, $matches)){
				$host = isset($matches[1])? $matches[1] : false;
			};
			if($host){
				//反转字符串
				$host_rev = strrev($host);
				foreach($allow_refre as $val){
					//支持通配符*
					$ref = str_replace('*', '', $val);
					//检查是否允许的来源
					if(($ref == $host) || ($ref!=$val && strpos($host_rev, strrev($ref))===0)){
						$interrupt = false;
						break;
					}
				}
			}
		}
	
		if($interrupt){
			if($isJs){
				APP::ajaxRst(false, '2100003','非法访问');
			}else{
				F::error('非法访问');
			}
		}
		return true;
	}
	
	// 简单的权限判断
	function _checkGroupPermission( $return=FALSE ) 
	{
		if ( $return ) { return 1==USER::getAdmin('group_id'); }
		if ( 1!=USER::getAdmin('group_id') ) {APP::ajaxRst(FALSE, '300010', '没有权限');}
	}
	
	/**
	 * 处理api返回的错误，在api错误码前加1
	 * @param array $ret
	 */
	public function apiException( $ret=array() ) 
	{
		if (is_array($ret) && isset($ret['errno'])) {
			APP::ajaxRst(false, '1'.$ret['errno'], $ret['err']);
		}
		return true;
	}
}
